<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<link rel=stylesheet href="/xbt.css">
<title>UDP tracker protocol</title>
<table width="100%">
	<tr>
		<td align=left valign=bottom><h1>UDP tracker protocol</h1>
		<td align=right valign=bottom><a href="/">Home</a>
</table>
<hr>
<h2>Introduction</h2>
<p>
The UDP tracker protocol is a high-performance low-overhead BitTorrent tracker protocol. URLs for this protocol look like udp://tracker:port.

<p>
<a href="http://azureus.sourceforge.net/">Azureus</a>, <a href="client">XBT Client</a> and <a href="tracker">XBT Tracker</a> support this protocol.

<p>
All values are send in network byte order (big endian). Do not expect packets to be exactly of a certain size. Future extensions could increase the size of packets.

<p>
Set n to 0.<br>
If no response is received after 60 * 2 ^ n seconds, resend the connect request and increase n.<br>
If a response is received, reset n to 0.<br>

<hr>
<h2>HTTP vs UDP</h2>

<ul>
	<li>Ethernet: 14 bytes
	<li>IP: 20 bytes
	<li>TCP: 20 bytes
	<li>UDP: 8 bytes
</ul>

<table>
<tr><th>Protocol<th>Packets<th>Non-user<th>User<th>Total
<tr><td>HTTP<td align=right>10<td align=right>540<td align=right>247 + 119 + 6 * N = 366 + 6 * N<td align=right>906 + 6 * N
<tr><td>UDP<td align=right>4<td align=right>168<td align=right>16 + 16 + 98 + 20 + 6 * N = 150 + 6 * N<td align=right>318 + 6 * N
<tr><td>HTTP - UDP<td align=right>6<td align=right>372<td align=right>216<td align=right>588
<tr><td>HTTP / UDP<td align=right>2.5<td align=right>3.2<td align=right>1.5<td align=right>2.0
</table>

<p>
The UDP tracker protocol uses (less than) 50% of the bandwidth the HTTP tracker protocol uses.
And because UDP is stateless, limits to the number of (open) TCP connections a router or server can handle, do not apply.

<hr>
<h2>Structures</h2>

<p>
Before announcing or scraping, you have to obtain a connection ID.

<ol>
	<li>Choose a (random) transaction ID.
	<li>Fill the connect input structure.
	<li>Send the packet.
</ol>

<table>
<caption>connect input</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>64-bit integer<td>connection_id<td align=right>0x41727101980
<tr><td align=right>8<td>32-bit integer<td>action<td align=right>0
<tr><td align=right>12<td>32-bit integer<td>transaction_id
<tr><td align=right>16
</table>

<ol>
	<li>Receive the packet.
	<li>Check whether the packet is at least 16 bytes.
	<li>Check whether the transaction ID is equal to the one you chose.
	<li>Check whether the action is connect.
	<li>Store the connection ID for future use.
</ol>

<table>
<caption>connect output</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>32-bit integer<td>action<td align=right>0
<tr><td align=right>4<td>32-bit integer<td>transaction_id
<tr><td align=right>8<td>64-bit integer<td>connection_id
<tr><td align=right>16
</table>

<ol>
	<li>Choose a (random) transaction ID.
	<li>Fill the announce input structure.
	<li>Send the packet.
</ol>

<table>
<caption>announce input</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>64-bit integer<td>connection_id
<tr><td align=right>8<td>32-bit integer<td>action<td align=right>1
<tr><td align=right>12<td>32-bit integer<td>transaction_id
<tr><td align=right>16<td>20-byte string<td>info_hash
<tr><td align=right>36<td>20-byte string<td>peer_id
<tr><td align=right>56<td>64-bit integer<td>downloaded
<tr><td align=right>64<td>64-bit integer<td>left
<tr><td align=right>72<td>64-bit integer<td>uploaded
<tr><td align=right>80<td>32-bit integer<td>event
<tr><td align=right>84<td>32-bit integer<td>IP address<td align=right>0
<tr><td align=right>88<td>32-bit integer<td>key
<tr><td align=right>92<td>32-bit integer<td>num_want<td align=right>-1
<tr><td align=right>96<td>16-bit integer<td>port
<tr><td align=right>98
</table>

<ol>
	<li>Receive the packet.
	<li>Check whether the packet is at least 20 bytes.
	<li>Check whether the transaction ID is equal to the one you chose.
	<li>Check whether the action is announce.
	<li>Do not announce again until interval seconds have passed or an event has happened.
</ol>

<table>
<caption>announce output</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>32-bit integer<td>action<td align=right>1
<tr><td align=right>4<td>32-bit integer<td>transaction_id
<tr><td align=right>8<td>32-bit integer<td>interval
<tr><td align=right>12<td>32-bit integer<td>leechers
<tr><td align=right>16<td>32-bit integer<td>seeders
<tr><td align=right>20 + 6 * n<td>32-bit integer<td>IP address
<tr><td align=right>24 + 6 * n<td>16-bit integer<td>TCP port
<tr><td align=right>20 + 6 * N
</table>

<p>
Up to about 74 torrents can be scraped at once. A full scrape can't be done with this protocol.

<ol>
	<li>Choose a (random) transaction ID.
	<li>Fill the scrape input structure.
	<li>Send the packet.
</ol>

<table>
<caption>scrape input</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>64-bit integer<td>connection_id
<tr><td align=right>8<td>32-bit integer<td>action<td align=right>2
<tr><td align=right>12<td>32-bit integer<td>transaction_id
<tr><td align=right>16 + 20 * n<td>20-byte string<td>info_hash
<tr><td align=right>16 + 20 * N
</table>

<ol>
	<li>Receive the packet.
	<li>Check whether the packet is at least 8 bytes.
	<li>Check whether the transaction ID is equal to the one you chose.
	<li>Check whether the action is scrape.
</ol>

<table>
<caption>scrape output</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>32-bit integer<td>action<td align=right>2
<tr><td align=right>4<td>32-bit integer<td>transaction_id
<tr><td align=right>8 + 12 * n<td>32-bit integer<td>seeders
<tr><td align=right>12 + 12 * n<td>32-bit integer<td>completed
<tr><td align=right>16 + 12 * n<td>32-bit integer<td>leechers
<tr><td align=right>8 + 12 * N
</table>

<p>
If the tracker encounters an error, it might send an error packet.

<ol>
	<li>Receive the packet.
	<li>Check whether the packet is at least 8 bytes.
	<li>Check whether the transaction ID is equal to the one you chose.
</ol>

<table>
<caption>error output</caption>
<tr><th>Offset<th>Size<th>Name<th>Value
<tr><td align=right>0<td>32-bit integer<td>action<td align=right>3
<tr><td align=right>4<td>32-bit integer<td>transaction_id
<tr><td align=right>8<td>string<td>message
</table>

<p>
If the tracker requires authentication, an authentication structure has to be appended to every packet you send to the tracker.
The hash is the first 8 bytes of sha1(input + username + sha1(password)).

<table>
<caption>authenticate input</caption>
<tr><th>Offset<th>Size<th>Name
<tr><td align=right>0<td>8-byte zero-padded string<td>username
<tr><td align=right>8<td>8-byte string<td>hash
<tr><td align=right>16
</table>

<hr>
<h2>Actions</h2>

<ul>
	<li>0: connect
	<li>1: announce
	<li>2: scrape
	<li>3: error
</ul>

<hr>
<h2>Events</h2>

<ul>
	<li>0: none
	<li>1: completed
	<li>2: started
	<li>3: stopped
</ul>
<hr>
<div>
	<a href="http://sourceforge.net/projects/xbtt/"><img src="http://sourceforge.net/sflogo.php?group_id=94951;type=1" alt="XBT project at SF"></a>
	<a href="http://sourceforge.net/donate/index.php?group_id=94951"><img src="http://images.sourceforge.net/images/project-support.jpg" alt="Donate to this project"></a>
	<a href="http://w3.org/"><img src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a>
	<a href="http://w3.org/"><img src="http://w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a>
</div>